﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace EcoSystem
{
    public class RegionAppService : CrudAppService<
        Region,
        RegionDto,
        string,
        GetRegionInput,
        CreateOrUpdateRegionDto,
        CreateOrUpdateRegionDto>, IRegionAppService
    {
        public RegionAppService(IRepository<Region, string> repository) : base(repository)
        {
        }

        public override async Task<PagedResultDto<RegionDto>> GetListAsync(GetRegionInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking()
                      .WhereIf(!input.Name.IsNullOrWhiteSpace(), x => x.Name == input.Name || x.FullName.Contains(input.Name) || x.ParentName.Contains(input.Name))
                      .WhereIf(!input.Code.IsNullOrWhiteSpace(), x => x.Id.StartsWith(input.Code))
                      .WhereIf(!input.ParentId.IsNullOrWhiteSpace(), x => x.ParentId.StartsWith(input.ParentId))
                      .WhereIf(input.Level.HasValue, x => input.Level.Value.HasFlag(x.Level))
                      .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var total = await query.CountAsync();
            var items = await query.OrderByDescending(x => x.Id).PageBy(input).ToListAsync();
            return new PagedResultDto<RegionDto>()
            {
                Items = await MapToGetListOutputDtosAsync(items),
                TotalCount = total
            };
        }

        public async Task<List<RegionDto>> GetAllListAsync(GetRegionInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking()
                      .WhereIf(!input.Name.IsNullOrWhiteSpace(), x => x.Name == input.Name || x.FullName.Contains(input.Name) || x.ParentName.Contains(input.Name))
                      .WhereIf(!input.Code.IsNullOrWhiteSpace(), x => x.Id.StartsWith(input.Code))
                      .WhereIf(!input.ParentId.IsNullOrWhiteSpace(), x => x.ParentId.StartsWith(input.ParentId))
                      .WhereIf(input.Level.HasValue, x => input.Level.Value.HasFlag(x.Level))
                      .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var items = await query.OrderByDescending(x => x.Id).ToListAsync();
            return await MapToGetListOutputDtosAsync(items);
        }

        /// <summary>
        /// 返回目录树结构
        /// </summary>
        /// <param name="bucketName"></param>
        /// <returns></returns>
        public async Task<List<RegionTreeDto>> GetTreeAsync(GetRegionTreeInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking()
               .WhereIf(!input.Name.IsNullOrWhiteSpace(), x => x.Name == input.Name || x.FullName.Contains(input.Name) || x.ParentName.Contains(input.Name))
               .WhereIf(!input.Code.IsNullOrWhiteSpace(), x => x.Id.StartsWith(input.Code))
               .WhereIf(!input.ParentId.IsNullOrWhiteSpace(), x => x.ParentId.StartsWith(input.ParentId))
               .WhereIf(input.Level.HasValue, x => input.Level.Value.HasFlag(x.Level))
               .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var rows = await query.OrderByDescending(x => x.Id).ToListAsync();


            var allItems = ObjectMapper.Map<List<Region>, List<RegionTreeDto>>(rows);

            var items = allItems.Where(x => string.IsNullOrEmpty(x.ParentId)).ToList();
            foreach (var item in items)
            {
                var subItems = GetChildrenItems(item.Id, allItems);
                if (subItems.Count > 0)
                {
                    item.Children = subItems;
                }
            }
            return items;
        }

        /// <summary>
        /// 获取下级节点数据
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="allItems"></param>
        /// <returns></returns>
        private List<RegionTreeDto> GetChildrenItems(string parentId, List<RegionTreeDto> allItems)
        {
            var list = allItems.Where(x => x.ParentId == parentId).ToList();
            foreach (var item in list)
            {
                var subItems = GetChildrenItems(item.Id, allItems);
                if (subItems.Count > 0)
                {
                    item.Children = subItems;
                }
            }
            return list;
        }

    }
}
